package pers.burgess.fsm.server.core;

import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import pers.burgess.fsm.model.Message;
import pers.burgess.fsm.server.util.FileUtil;

public class Server {

	private ServerSocket serverSocket = null;

	public Server(int port) throws IOException {
		this.serverSocket = new ServerSocket(port);
	}

	private class ServerThread extends Thread {

		private Socket socket = null;
		private ObjectInputStream ois = null;
		private ObjectOutputStream oos = null;

		public ServerThread(Socket socket) {
			this.socket = socket;
		}

		@Override
		public void run() {
			if (socket != null) {
				boolean keepAlive = true;
				try {
					// default path
					String currentPath = (String) System.getProperties().get("user.home");

					ois = new ObjectInputStream(socket.getInputStream());
					oos = new ObjectOutputStream(socket.getOutputStream());

					// transfer default path to client
					oos.writeObject(new Message(currentPath, "", Message.SERVER_MSG));
					oos.flush();
					
					Message innerMessage = null;

					while (keepAlive) {

						// Message from client
						innerMessage = (Message) ois.readObject();

						Message outerMessage = null;

						String command = innerMessage.getMessage().trim();
						String[] commandSplit = command.split(" ");

						if (commandSplit[0].toUpperCase().equals("EXIT")) {
							keepAlive = false;
						} else {

							if (commandSplit[0].toUpperCase().equals("LS")) {
								// command -> LS
								// return the message about current path
								outerMessage = new Message(currentPath, FileUtil.getDirInfos(new File(currentPath)),
										Message.SERVER_MSG);
							} else {

								if (commandSplit[0].toUpperCase().startsWith("CD")) {
									
									// command -> CD
									// changed dictionary
									File newDictionary = new File(commandSplit[commandSplit.length - 1].trim());
									
									if (newDictionary.exists() && newDictionary.isDirectory()) {
										currentPath = newDictionary.getAbsolutePath();
										outerMessage = new Message(currentPath, "change to " + currentPath, Message.SERVER_MSG);
									} else {
										outerMessage = new Message(currentPath, "not exists", Message.SERVER_MSG);
									}
									
								} else if (commandSplit[0].toUpperCase().startsWith("CP")) {

									String select = commandSplit[commandSplit.length - 2].trim();
									String targetPath = commandSplit[commandSplit.length - 1].trim();

									long start = System.currentTimeMillis();
									boolean result = FileUtil.copyFile(new File(new File(currentPath), select),
											new File(targetPath));
									outerMessage = new Message(currentPath, result ? "copy complete, use time: " + (System.currentTimeMillis() - start) + "ms" : "copy fail",
											Message.SERVER_MSG);
								} else {
									// operate target
									String select = commandSplit[commandSplit.length - 1].trim();

									if (command.toUpperCase().startsWith("RM -F")) {
										boolean result = FileUtil.deleteAll(new File(new File(currentPath), select));
										outerMessage = new Message(currentPath,
												result ? "delete complete" : "delete fail", Message.SERVER_MSG);
									} else if (commandSplit[0].toUpperCase().startsWith("RM")) {
										boolean result = FileUtil.deleteSingle(new File(new File(currentPath), select));
										outerMessage = new Message(currentPath,
												result ? "delete complete" : "delete fail", Message.SERVER_MSG);
									}
								}
							}

							if (outerMessage == null) {
								outerMessage = new Message(currentPath, "unknown command", Message.SERVER_MSG);
							}

							oos.writeObject(outerMessage);
							oos.flush();
						}

					}

				} catch (Exception e) {
					keepAlive = false;
					e.printStackTrace();
				} finally {
					System.out.println("disconnect");
					try {
						if (ois != null)
							ois.close();
						if (oos != null)
							oos.close();
						if (socket != null)
							socket.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}

	public void start() {
		System.out.println("Server start...");
		while (true) {
			try {
				Socket socket = serverSocket.accept();
				new ServerThread(socket).start();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
